package linuxbox.admin.logic;

import java.security.*;
import java.util.*;

import linuxbox.*;
import linuxbox.admin.bean.*;
import linuxbox.admin.exception.*;
import linuxbox.exception.*;
import linuxbox.status.logic.*;
import linuxbox.util.*;

public class UserManager {
    protected static UserManager staticInstance = null;

    public final static int USERNAME_FORMAT_ALL = 1;
    public final static int USERNAME_FORMAT_LOGINID = 2;
    public final static int USERNAME_FORMAT_NAME = 3;

    protected DbAdapter db = null;
    protected UserCtrlHome userHome = null;
    protected DeptHome deptHome = null;

    public static UserManager getInstance() {
        if (staticInstance == null) {
            staticInstance = new UserManager();
        }

        return staticInstance;
    }

    private UserManager() {
        init();
    }

    private void init() {
        userHome = new UserCtrlHome();
        deptHome = new DeptHome();

        /*try {
            db = new DbAdapter(false);
            userHome = new UserCtrlHome(db);
        } catch (Exception e) {
            BoxStatic.logger.debug("UserManager init error: " + e.getMessage());
        }*/
    }

    public int userLogin(String sLoginID, String sPassword)
    throws LinuxboxException {
        String sPwdTmp1, sPwdTmp2;

        UserCtrlKey key = null;
        UserCtrlBean bean = null;

        try {
            key = userHome.findByLoginID(sLoginID);
            bean = new UserCtrlBean(key);
            sPwdTmp1 = bean.getPassword();
            sPwdTmp2 = encode(sPassword);
        } catch (Exception e) {
            throw LinuxboxException.LOGIN_ERROR;
        }

        if (sPwdTmp1.equals(sPwdTmp2)) {
            return key.m_iID;
        } else {
            throw LinuxboxException.LOGIN_ERROR;
        }

        //addUserStatus(id);
    }

    protected void addUserStatus(int userid) throws LinuxboxException {
        try {
            UserCtrlBean bean = new UserCtrlBean(new UserCtrlKey(userid));
            StatusObject so = new StatusObject(userid, bean.getLoginID(),
                bean.getFirstName(), bean.getLastName(),
	            bean.getDeptID(), StatusManager.ONLINE);
            StatusManager.getInstance().addStatus(so);
	    } catch (Exception e) {
            throw LinuxboxException.LOGIN_ERROR;
        }
    }

    public void userLogout(int userid) throws LinuxboxException {
        //StatusManager.getInstance().moveStatusToHistory(userid);
    }

    /**
     * used to encode password
     */
    private static String encode(String source) {
        byte[] dest_msg = null;

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            dest_msg = md.digest(source.getBytes());
        } catch (Exception e) {
            BoxStatic.logger.debug("couldn't make digest of partial content");
        }

        return byteArrayToString(dest_msg);
    }

    private static String byteArrayToString(byte[] ab) {
        if (ab == null)
            return "";

        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < ab.length; i++) {
            String str = Integer.toHexString(ab[i] & 0xff);
            if (str.length() == 1)
                sb.append("0");

            sb.append(str);
        }

        return sb.toString();
    }

    public User getUser(String userid) throws UserManagerException {
        User user = null;
        try {
            List keys = userHome.findBySql(" where loginid='"+userid+"'");

            //Should only return one
            UserCtrlKey key = (UserCtrlKey)keys.get(0);
            UserCtrlBean bean = new UserCtrlBean(key);

            String sLoginID = bean.getLoginID();
            String sPassword = bean.getPassword();
            String sFirstName = bean.getFirstName();
            String sLastName = bean.getLastName();
            long lUserRights = bean.getUserRights();
            long lUserRights2 = bean.getUserRights2();
            boolean bNoExpire = bean.getNoExpire();

            user = new User(sLoginID, sPassword, sFirstName,
                sLastName, lUserRights, lUserRights2, bNoExpire);

            user.setID(bean.getID());
            user.setAddress(bean.getAddress());
            user.setCity(bean.getCity());
            user.setState(bean.getState());
            user.setZipCode(bean.getZipCode());
            user.setPhone(bean.getPhone());
            user.setFax(bean.getFax());
            user.setMobile(bean.getMobile());
            user.setEmail(bean.getEmail());
            user.setManagerID(bean.getManagerID());
            user.setDeptID(bean.getDeptID());
            user.setDeptName(bean.getDeptName());
            user.setIsManager(bean.getIsManager());
            user.setDisable(bean.getDisable());
            user.setNote(bean.getNote());
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
        }

        return user;
    }

    public User getUser(int id) throws UserManagerException {
        UserCtrlKey key = new UserCtrlKey(id);
        return getUser(key);
    }

    public User getUser(UserCtrlKey key) throws UserManagerException {
        UserCtrlBean bean = null;
        User user = null;

        try {
            key = userHome.findByKey(key);

            bean = new UserCtrlBean(key);

            String sLoginID = bean.getLoginID();
            String sPassword = bean.getPassword();
            String sFirstName = bean.getFirstName();
            String sLastName = bean.getLastName();
            long lUserRights = bean.getUserRights();
            long lUserRights2 = bean.getUserRights2();
            boolean bNoExpire = bean.getNoExpire();

            user = new User(sLoginID, sPassword, sFirstName, sLastName, lUserRights,
                lUserRights2, bNoExpire);

            user.setID(bean.getID());
            user.setAddress(bean.getAddress());
            user.setCity(bean.getCity());
            user.setState(bean.getState());
            user.setZipCode(bean.getZipCode());
            user.setPhone(bean.getPhone());
            user.setFax(bean.getFax());
            user.setMobile(bean.getMobile());
            user.setEmail(bean.getEmail());
            user.setManagerID(bean.getManagerID());
            user.setDeptID(bean.getDeptID());
            user.setDeptName(bean.getDeptName());
            user.setIsManager(bean.getIsManager());
            user.setDisable(bean.getDisable());
            user.setNote(bean.getNote());
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
        }

        return user;
    }

    public List findUsers(String where) throws UserManagerException {
        List users = new ArrayList();
        try {
            List keys = userHome.findBySql(where);

            for (Iterator it = keys.iterator(); it.hasNext(); ) {
                UserCtrlKey key = (UserCtrlKey)it.next();
                UserCtrlBean bean = new UserCtrlBean(key);

                String sLoginID = bean.getLoginID();
                String sPassword = bean.getPassword();
                String sFirstName = bean.getFirstName();
                String sLastName = bean.getLastName();
                long lUserRights = bean.getUserRights();
                long lUserRights2 = bean.getUserRights2();
                boolean bNoExpire = bean.getNoExpire();

                User user = new User(sLoginID, sPassword, sFirstName,
                    sLastName, lUserRights, lUserRights2, bNoExpire);

                user.setID(bean.getID());
                user.setAddress(bean.getAddress());
                user.setCity(bean.getCity());
                user.setState(bean.getState());
                user.setZipCode(bean.getZipCode());
                user.setPhone(bean.getPhone());
                user.setFax(bean.getFax());
                user.setMobile(bean.getMobile());
                user.setEmail(bean.getEmail());
                user.setManagerID(bean.getManagerID());
                user.setDeptID(bean.getDeptID());
                user.setDeptName(bean.getDeptName());
                user.setIsManager(bean.getIsManager());
                user.setDisable(bean.getDisable());
                user.setNote(bean.getNote());

                users.add(user);
            }
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
        }

        return users;
    }

    public int[] getAllUsers() throws UserManagerException {
        int[] user_ids = null;

        try {
            List keys = userHome.findBySql(" order by lastname");
            //Vector keys = userHome.findBySql(" ");

            int length = keys.size();
            UserCtrlKey key = null;
            user_ids = new int[length];

            for (int i = 0; i < length; i++) {
                key = (UserCtrlKey)keys.get(i);
                user_ids[i] = key.m_iID;
            }
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
            throw new UserManagerException(e.getMessage());
        }

        return user_ids;
    }

    public int[] getAllUsers(String sortType) throws UserManagerException {
        int[] user_ids = null;

        try {
            List keys = userHome.findBySql(sortType);

            int length = keys.size();
            UserCtrlKey key = null;
            user_ids = new int[length];

            for (int i = 0; i < length; i++) {
                key = (UserCtrlKey)keys.get(i);
                user_ids[i] = key.m_iID;
            }
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
            throw new UserManagerException(e.getMessage());
        }

        return user_ids;
    }

    public int[] getAllManagers() throws UserManagerException {
        int[] user_ids = null;

        try {
            List keys = userHome.findBySql(" where is_manager=1 order by lastname");
            //Vector keys = userHome.findBySql(" ");

            int length = keys.size();
            UserCtrlKey key = null;
            user_ids = new int[length];

            for (int i = 0; i < length; i++) {
                key = (UserCtrlKey)keys.get(i);
                user_ids[i] = key.m_iID;
            }
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
            throw new UserManagerException(e.getMessage());
        }

        return user_ids;
    }

    public boolean addUser(User user) throws UserManagerException {
        try {
            String password = user.getPassword();
            password = encode(password);
            user.setPassword(password);

            UserCtrlKey key = userHome.create(user);
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
            throw new UserManagerException(e.getMessage());
        }

        return true;
    }

    public void changePassword(int id, String newPass)
    throws LinuxboxException {
        try {
            newPass = encode(newPass);
            UserCtrlBean bean = new UserCtrlBean(new UserCtrlKey(id));
            bean.setPassword(newPass);
            bean.store();
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
            throw LinuxboxException.FAIL_CHANG_PASSWD;
        }
    }

    public boolean modifyUser(User user) throws UserManagerException {
        BoxStatic.logger.debug("I am in UserManager - modifyUser now ... ");

        UserCtrlKey key = new UserCtrlKey(user.getID());
        UserCtrlBean bean = null;

        try {
            key = userHome.findByKey(key);

            bean = new UserCtrlBean(key);

            String sFirstName = user.getFirstName();
            String sLastName = user.getLastName();
            String sPassword = user.getPassword();
            long lUserRights = user.getUserRights();
            long lUserRights2 = user.getUserRights2();
            boolean bDisable = user.getDisable();
            boolean bNoExpire = user.getNoExpire();
            String sNote = user.getNote();

            bean.setFirstName(sFirstName);
            bean.setLastName(sLastName);

            if (sPassword != null && !sPassword.equals("")) {
                sPassword = encode(sPassword);
                bean.setPassword(sPassword);
            }
            if (lUserRights != -1)
                bean.setUserRights(lUserRights);
            if (lUserRights2 != -1)
                bean.setUserRights2(lUserRights2);

            bean.setAddress(user.getAddress());
            bean.setCity(user.getCity());
            bean.setState(user.getState());
            bean.setZipCode(user.getZipCode());
            bean.setPhone(user.getPhone());
            bean.setFax(user.getFax());
            bean.setMobile(user.getMobile());
            bean.setEmail(user.getEmail());
            bean.setManagerID(user.getManagerID());
            bean.setDeptID(user.getDeptID());
            bean.setIsManager(user.getIsManager());
            bean.setDisable(bDisable);
            bean.setNoExpire(bNoExpire);

            if (sNote != null && !sNote.equals(""))
                bean.setNote(sNote);

            bean.store();
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
            throw new UserManagerException(e.getMessage());
        }

        BoxStatic.logger.debug("I am leaving UserManager - modifyUser now ... ");
        return true;
    }

    public void deleteUser(int id) throws UserManagerException {
        BoxStatic.logger.debug("I am in UserManager - deleteUser now ... ");

        UserCtrlKey key = new UserCtrlKey(id);
        UserCtrlBean bean = null;

        try {
            key = userHome.findByKey(key);
            userHome.remove(key);
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
        }

        BoxStatic.logger.debug("I am leaving UserManager - deleteUser now ... ");
    }

/**************************************************************

Department Management Methods

**************************************************************/

    public Department getDepartment(DeptKey id) throws UserManagerException {
        Department dept = null;

        try {
            DeptKey key = deptHome.findByKey(id);
            DeptBean bean = new DeptBean(key);
            dept = new Department(bean.getID(), bean.getName());
            dept.setAddress(bean.getAddress());
            dept.setPhone(bean.getPhone());
            dept.setEmail(bean.getEmail());
            dept.setDisable(bean.getDisable());
            dept.setNote(bean.getNote());

        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
        }

        return dept;
    }

    public List getAllDepartments() throws UserManagerException {
        try {
            return deptHome.findBySql(" order by name");
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
            throw new UserManagerException(e.getMessage());
        }
    }

    public DeptKey addDepartment(Department dept) throws UserManagerException {
        try {
            return deptHome.create(dept);
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
            throw new UserManagerException(e.getMessage());
        }
    }

    public boolean modifyDepartment(Department dept) throws UserManagerException {
        try {
            BoxStatic.logger.debug("I am in UserManager - modifyDepartment now ... ");

            DeptKey key = new DeptKey(dept.getID());
            DeptBean bean = new DeptBean(key);

            String sName = dept.getName();
            boolean bDisable = dept.getDisable();
            String sNote = dept.getNote();

            bean.setName(sName);
            bean.setAddress(dept.getAddress());
            bean.setPhone(dept.getPhone());
            bean.setEmail(dept.getEmail());
            bean.setDisable(bDisable);

            if (sNote != null && !sNote.equals(""))
                bean.setNote(sNote);

            bean.store();

            BoxStatic.logger.debug("I am leaving UserManager - modifyDepartment now ... ");
            return true;
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
            throw new UserManagerException(e.getMessage());
        }
    }

    public void deleteDepartment(int id) throws UserManagerException {
        try {
            BoxStatic.logger.debug("I am in UserManager - deleteDepartment now ... ");

            DeptKey key = new DeptKey(id);
            deptHome.remove(key);

            BoxStatic.logger.debug("I am leaving UserManager - deleteDepartment now ... ");
        } catch (Exception e) {
            BoxStatic.logger.debug(e.getMessage());
        }
    }

    /**************************************************************
     *
     * UserGrp Management Methods
     *
     **************************************************************/

    public UserGrpKey addUserGrp(UserGrpObject obj) throws LinuxboxException {
        UserGrpKey key = null;

        UserGrpBean bean = new UserGrpBean();
        bean.create(obj);

        key = new UserGrpKey(bean.getID());

        return key;
    }

    public void removeUserGrp(UserGrpKey key) throws LinuxboxException {
        UserGrpBean bean = new UserGrpBean(key);
        bean.remove();
    }

    public void removeUserGrp(int id) throws LinuxboxException {
        removeUserGrp(new UserGrpKey(id));
    }

    public void updateUserGrp(UserGrpObject entry) throws LinuxboxException {
        UserGrpBean bean = new UserGrpBean(new UserGrpKey(entry.getID()));
        bean.copyFrom(entry);
        bean.store();
    }

    public Collection getAllUserGrps(String sort) throws LinuxboxException {
        String sql = "";
        if (sort != null) sql += sort;
        UserGrpBean bean = new UserGrpBean(null);
        return bean.findBySql(sql);
    }

    public UserGrpObject getUserGrp(UserGrpKey key) throws LinuxboxException {
        UserGrpObject entry = null;

        UserGrpBean bean = new UserGrpBean(key);
        bean.load();
        entry = new UserGrpObject();
        entry.copyFrom(bean);
        entry.setMemberCount(getGrpMemberCount(entry.getID()));

        return entry;
    }

    public UserGrpObject getUserGrp(int id) throws LinuxboxException {
        return getUserGrp(new UserGrpKey(id));
    }

    public int getGrpMemberCount(int grpID) throws LinuxboxException {
        UserGrpMapBean bean = new UserGrpMapBean();
        return bean.getMemberCount(grpID);
    }

    /**************************************************************
     *
     * UserGrpMap Management Methods
     *
     **************************************************************/
    public UserGrpMapKey addUserGrpMap(UserGrpMapObject obj) throws LinuxboxException {
        UserGrpMapKey key = null;

        UserGrpMapBean bean = new UserGrpMapBean();
        bean.create(obj);

        key = new UserGrpMapKey(bean.getID());

        return key;
    }

    public void removeUserGrpMap(UserGrpMapObject obj) throws LinuxboxException {
        UserGrpMapBean bean = new UserGrpMapBean();
        bean.remove(obj);
    }

    /*public void removeUserGrpMap(UserGrpMapKey key) throws LinuxboxException {
        UserGrpMapBean bean = new UserGrpMapBean(key);
        bean.remove();
    }

    public void removeUserGrpMap(int id) throws LinuxboxException {
        removeUserGrpMap(new UserGrpMapKey(id));
    }*/

    public Collection getGrpMembers(int groupID) throws LinuxboxException {
        UserGrpBean bean = new UserGrpBean();
        return bean.findMembers(groupID, true);
    }

    public Collection getNotGrpMembers(int groupID) throws LinuxboxException {
        UserGrpBean bean = new UserGrpBean();
        return bean.findMembers(groupID, false);
    }

    /***********************************************
     *
     * debug methods
     *
     **********************************************/
    public static void main(String[] args) {
        try {
            Class keepStatics = BoxStatic.class;
            //BoxInit.initTestEnv();

            //showAllGrps();
            //UserGrpObject ugo = new UserGrpObject(3, "mytest", 0, "this is mytest");
            UserGrpMapObject ugmo = new UserGrpMapObject(1, 1);
            UserManager um = UserManager.getInstance();
            //um.addUserGrpMap(ugmo);
            //um.removeUserGrpMap(1);
            //um.removeUserGrpMap(2);
            //um.removeUserGrp(3);
            //showAllGrps();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void showAllGrps() throws Exception {
        UserManager um = UserManager.getInstance();
        for (Iterator it = um.getAllUserGrps("").iterator(); it.hasNext(); ) {
            UserGrpKey key = (UserGrpKey)it.next();
            UserGrpObject ugo = um.getUserGrp(key);
            print(ugo.dump());
        }
    }

    public static void print(Object obj) {
        System.out.println(obj);
    }

  /**
   * getUserDisplayName
   * TODO: check language also
   * @param userID int, format int
   * @return String
   */
  public String getUserDisplayName(int userID, int format) throws Exception
  {
    User user = getUser(userID);
    if (user == null)
      return "";
    else
    {
    //TODO: check language
      StringBuffer str = new StringBuffer();
      switch (format)
      {
        case USERNAME_FORMAT_ALL:
        {
          str.append(user.getLastName());
          str.append(",");
          str.append(user.getFirstName());
          str.append("(");
          str.append(user.getLoginID());
          str.append(")");
          break;
        }
        case USERNAME_FORMAT_LOGINID:
        {
          str.append(user.getLoginID());
          break;
        }

        case USERNAME_FORMAT_NAME:
        {
          str.append(user.getLastName());
          str.append(",");
          str.append(user.getFirstName());
          break;
        }
      }
      return str.toString();
    }
  }
}
